package cn.bqjr.eily.core.serializer;

import cn.bqjr.eily.core.annotation.TransferKV;
import cn.bqjr.eily.utils.SpringContextUtils;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.List;
import java.util.Objects;

/**
 * jackson JSON KV转换器
 *
 * @author hillfly
 */
public class JacksonFieldKVSerializer extends JsonSerializer<String> implements ContextualSerializer {

    private TransferKV kvAnno;
    private JsonFieldSerializer serializer;

    public JacksonFieldKVSerializer() {

    }

    public JacksonFieldKVSerializer(TransferKV kv, JsonFieldSerializer serializer) {
        this.kvAnno = kv;
        this.serializer = serializer;
    }

    @Override
    public void serialize(String s, JsonGenerator jsonGenerator,
                          SerializerProvider serializerProvider)
            throws IOException {

        if (StringUtils.isEmpty(s)) {
            jsonGenerator.writeString(s);
        } else {
            if (null != kvAnno && null != serializer) {
                jsonGenerator.writeString(serializer.doSerialize(kvAnno, s));
            } else {
                jsonGenerator.writeString(s);
            }
        }
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider,
                                              BeanProperty beanProperty)
            throws JsonMappingException {
        if (beanProperty != null) {
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
                TransferKV anno = beanProperty.getAnnotation(TransferKV.class);
                if (anno != null) {
                    // 遍历所有字段序列化bean，查找对应字段的序列化实现
                    List<JsonFieldSerializer> serializers =
                            SpringContextUtils.getBeans(JsonFieldSerializer.class);
                    JsonFieldSerializer serializer = serializers.stream()
                                                                .filter(s -> s.accept(anno))
                                                                .findFirst()
                                                                .get();
                    JacksonFieldKVSerializer kvSerializer = new JacksonFieldKVSerializer(anno, serializer);
                    return kvSerializer;
                }
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }
}
